package main

import (
	"flag"
	"fmt"
	"golang.org/x/net/icmp"
	"golang.org/x/net/ipv4"
	"log"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"syscall"
	"time"
)

func  CheckIp(targetIP string)  {

	// 创建 ICMP 连接
	conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
	if err != nil {
		fmt.Printf("ListenPacket error: %v\n", err)
		return
	}
	defer conn.Close()

	// 定义变量记录连续离线次数
	offlineCount := 0

	// 不断循环检测网络状态
	for {
		// 构造 ICMP 消息
		msg := icmp.Message{
			Type: ipv4.ICMPTypeEcho, Code: 0,
			Body: &icmp.Echo{
				ID: os.Getpid() & 0xffff, Seq: offlineCount + 1,
				Data: []byte("Hello, World!"),
			},
		}
		msgBytes, err := msg.Marshal(nil)
		if err != nil {
			fmt.Printf("Marshal error: %v\n", err)
			continue
		}

		// 发送 ICMP 消息
		dstAddr, err := net.ResolveIPAddr("ip4", targetIP)
		if err != nil {
			fmt.Printf("ResolveIPAddr error: %v\n", err)
			continue
		}
		_, err = conn.WriteTo(msgBytes, dstAddr)
		if err != nil {
			fmt.Printf("WriteTo error: %v\n", err)
			continue
		}

		// 接收 ICMP 响应
		buffer := make([]byte, 1500)
		conn.SetReadDeadline(time.Now().Add(time.Second * 3))
		n, peer, err := conn.ReadFrom(buffer)
		if err != nil {
			fmt.Printf("ReadFrom error: %v\n", err)
			offlineCount++
			if offlineCount >= 5 {
				fmt.Println("Network is offline. Restart dialing program.")
				// 在此处重新运行拨号程序
				offlineCount = 0
			}
			continue
		}

		// 解析 ICMP 响应
		icmpMsg, err := icmp.ParseMessage(1, buffer[:n])
		if err != nil {
			//fmt.Printf("ParseMessage error: %v\n", err)
			continue
		}
		switch icmpMsg.Type {
		case ipv4.ICMPTypeEchoReply:
			fmt.Printf("Network is ok. The response from %v.\n", peer)
			offlineCount = 0
		default:
			fmt.Printf("Network is not ok. The response from %v.\n", peer)
			offlineCount++
			if offlineCount >= 5 {
				fmt.Println("Network is offline. Restart dialing program.")
				// 在此处重新运行拨号程序
				offlineCount = 0
			}
		}

		// 等待 5 秒钟
		time.Sleep(time.Second * 5)
	}
}
func daemonize() {
	// 创建子进程并退出父进程
	cmd := exec.Command(os.Args[0], os.Args[1:]...)
	cmd.Stdin = nil
	cmd.Stdout = nil
	cmd.Stderr = nil
	err := cmd.Start()
	if err != nil {
		fmt.Printf("Start child process error: %v\n", err)
		return
	}
	fmt.Printf("Child process ID: %d\n", cmd.Process.Pid)
	syscall.Setpgid(cmd.Process.Pid, 0)
	syscall.Umask(0)
	os.Exit(0)

	// 忽略 SIGHUP 信号
	signal.Ignore(syscall.SIGHUP)
}
func main() {
	// 解析命令行参数
	var targetIP string
	var deamonflag string
	flag.StringVar(&targetIP, "ip", "", "target IP address")
	flag.StringVar(&deamonflag, "d", "", "deamon flag  set 1  enable")

	flag.Parse()

	if targetIP == "" {
		fmt.Println("Please specify target IP address.")
		flag.Usage()
		return
	}
	if deamonflag == "1"  {
		log.Println("deamon flag")
		daemonize()
	}
	CheckIp(targetIP)
}